﻿using System;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

using System.Diagnostics;

namespace Organized
{
    public class Actor : Drawable3dComponent
    {
        //the model to draw
        public Model model;

        public Vector3 pivotOffset = Vector3.Zero;

        public float ZSpeed;
        public bool Enabled = true;
        //tells you wether or not the object is in camera frustum
        public bool inFrustum;

        //the movement vector
        public Vector3 movement;
        public float distanceToCamera = 0;

        public Camera camera;
       
        public virtual float FacingDirection { get; set; }

        //actor name for debugging purposes
        public string Name = "noname";

        public bool FrustumTesting = true;

        Effect effect;

        Effect ModelEffect;

        Effect currentEffect;

        public Matrix[] transforms;

     
        public Matrix WorldMatrix
        {
            get { return worldMatrix; }
            set { worldMatrix = value; }
        }

        Matrix worldMatrix = Matrix.Identity;
        ContainmentType testCont;
        BoundingFrustum bf;

        Texture2D[] modelTextures;
        
 
        public Actor(Model Model, Lighting _light, Vector3 Position, GameScreen Parent) : base(_light, Position, Parent)
        {
            camera = Engine.Services.GetService<Camera>();          
            Setup(Model);
        }

       

        // setup method so we wont have to change both the constructors
        void Setup(Model Model)
        {
            effect = Engine.Content.Load<Effect>("Content/Effects/modelShader");
            ModelEffect = Engine.Content.Load<Effect>("Content/Effects/modeltest");
            this.model = Model;
            LoadModelEffect();            
            Scale = Vector3.One;
            EulerRotation = Vector3.Zero;
        }
       

        private void LoadModelEffect()
        {

            foreach (ModelMesh mesh in model.Meshes)
                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                    meshPart.Effect = effect.Clone(Engine.GraphicsDevice);
            
        }




        public void FrustumTest()
        {
            
              
             
                bf = new BoundingFrustum(camera.View * camera.Projection);
                testCont = bf.Contains(this.BoundingSphere);
                if(testCont == ContainmentType.Contains || testCont == ContainmentType.Intersects){

                    inFrustum = true;
                }
                else{
                    inFrustum = false;
                }
             
                   
          

        }

        public override void Update()
        {
            if (FrustumTesting)
            {
                FrustumTest();
            }
            base.Update();
        }

        public override void DrawDepthMap(){

           
            DrawModel("DepthMap");
        }

        public void DrawModel(string technique)
        {
       

            //Engine.GraphicsDevice.RenderState.DepthBufferEnable = false;
            Engine.GraphicsDevice.RenderState.DepthBufferWriteEnable = true;
            Engine.GraphicsDevice.RenderState.DepthBufferEnable = true;
           
           // Engine.GraphicsDevice.RenderState.DepthBufferWriteEnable = true;
            // loop through meshes an effects and set them to draw
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (Effect effect in mesh.Effects)
                {
                    // Set effect parameters
                    effect.CurrentTechnique = effect.Techniques[technique];
                    effect.Parameters["xWorld"].SetValue(transforms[mesh.ParentBone.Index] * worldMatrix);
                    effect.Parameters["xView"].SetValue(camera.View);
                    effect.Parameters["xProjection"].SetValue(camera.Projection);
                    
                    effect.Parameters["xEnableLighting"].SetValue(true);
                    effect.Parameters["xLightDirection"].SetValue(lighting.lightDirection);
                    effect.Parameters["xAmbient"].SetValue(lighting.ambientPower);
                }

                //draw the mesh
                mesh.Draw();
            }
           
        }

        public override void Draw()
        {

            //only draw if in frustum
            if (inFrustum || !FrustumTesting)
            {

             
                //add me to the component render list, for postproceccing a depthmap
                this.Parent.DrawableRenderList.Add(this);

                // Generate the world matrix
                WorldMatrix = MathUtil.CreateWorldMatrix((Position + pivotOffset), Rotation, Scale);
               
                transforms = new Matrix[model.Bones.Count];
                model.CopyAbsoluteBoneTransformsTo(transforms);

                DrawModel("Colored");
            }
        

        }
    }

}




        
